import axios from "axios";
import Bus from "./bus";
import store from "./store";
import ws from "./ws.ts"
const config = toRef(store);

export type user_config = {
    uR: number;
    mAH: number;
    aes: {
        start: number;
        end: number;
    };
    calib: {
        voltage: number;
        current: number;
    };
    afe: {
        ovt: number;
        uvt: number;
        occt: number;
        ocdt: number;
        ocdd: number;
        occd: number;
        scdd: number;
        scdt: number;
        cp_gc: number;
        cs_pt: number;
        vs_pt: number;
        bat_num: number;
    };
}
export type ota_config = {
    last: number,/* 从服务器获取的时间 */
    version: string,/* 从服务器获取的版本 */
    url: string,/* OTA 固件获取URL */
    ver_url: string,/* OTA固件版本获取URL */
    web_url: string,/* WEB OTA 文件获取URL */
    user: string,/* OTA 验证用户名 */
    pwd: string,/* OTA 验证用户密码 */
}

/* get_chip_info 👇 */
export type ChipInfo = {
    version: string,
    api_version: string,
    chip: string,
    time: string,
    mac: string,
    flash: number,
    io: number,
    ram: number,
}

export type AFEInfo = {
    voltage: number,
    bat: number[],
    bat_ah: number,
    bat_rah: number,
    current: number,
    mAh: number,
    mAh_chg: number,
    mAh_dsg: number,
    mWh: number,
    mWh_chg: number,
    mWh_dsg: number,
    mcu_temp: number,
    power: number,
    temp: number,
    time: number,
    state: {
        CHG: number,
        DSG: number,
        OCD: number,
        SCD: number,
        UV: number,
        OV: number,
        OCC: number,
        Alert: number,
        CS: number,
        VS: number,
        Load: number,
        AE: number,
    }
}

export type LogInfo = {
    time: number,
    voltage: number,
    current: number,
    power: number,
    temp: number,
    bat: number[],
}

export type LogEvent = {
    time: number,
    event: number,
    flag: number,
    state: number,
}

export type LogResult = {
    type: number,
    content: LogEvent | LogInfo,
}

export type LogList = {
    infos: {
        sec: LogInfo[],
        min: LogInfo[],
        hour: LogInfo[],
        day: LogInfo[],
    },
    events: LogEvent[]
}

interface WSResult {
    api: string,
    data: any | ChipInfo | LogResult,
    [propName: string]: unknown
}

let server_info: {
    chip: ChipInfo,
    infos: AFEInfo,
    log_list: LogList,
    user_config: user_config,
    set_config: user_config,
    ota: ota_config,
    set_ota: ota_config,
} = reactive({
    chip: {
        version: "1.0",
        chip: "测试数据",
        api_version: "1.0",
        io: 0,
        ram: 0,
        flash: 0,
        mac: "00:00:00:00:00:00",
        time: "2025/01/01 00:00:00",
    },
    infos: {
        voltage: 0,
        bat: [0, 0, 0, 0],
        bat_ah: 0,
        bat_rah: 0,
        current: 0,
        mAh: 0,
        mAh_chg: 0,
        mAh_dsg: 0,
        mWh: 0,
        mWh_chg: 0,
        mWh_dsg: 0,
        mcu_temp: 0,
        power: 0,
        temp: 0,
        time: 0,
        state: {
            CHG: 0,
            DSG: 0,
            OCD: 0,
            SCD: 0,
            UV: 0,
            OV: 0,
            OCC: 0,
            Alert: 0,
            CS: 0,
            VS: 0,
            Load: 0,
            AE: 0,
        }
    },
    user_config: {
        uR: 10000,
        mAH: 20000,
        aes: {
            start: 0.03,
            end: 0.001,
        },
        calib: {
            voltage: 1.0,
            current: 1.0,
        },
        afe: {
            ovt: 70,
            uvt: 179,
            occt: 0,
            ocdt: 0,
            ocdd: 0,
            occd: 0,
            scdd: 0,
            scdt: 0,
            cp_gc: 1,
            cs_pt: 0,
            vs_pt: 0,
            bat_num: 4,
        }
    },
    set_config: {

    },
    log_list: {
        infos: {
            sec: [],
            min: [],
            hour: [],
            day: [],
        },
        events: [],
    },
    ota: {
        last: 0,
        version: "0.0",
        url: "",
        ver_url: "",
        web_url: "",
        user: "",
        pwd: "",
    }
})
server_info.set_config = JSON.parse(JSON.stringify(server_info.user_config));
server_info.set_ota = JSON.parse(JSON.stringify(server_info.ota));

let handles: { [propName: string]: any } = {}
let ticks: { [propName: string]: any } = reactive({})
let cb_list: { [propName: string]: any } = {}

function get_msg(result: WSResult) {
    if (typeof result === 'string')
        result = JSON.parse(result);
    if (!('api' in result)) {
        ElMessage.error("api is null" + new String(JSON.stringify(result)));
        console.log("api is null", result);
        return;
    }

    // console.log(`收到消息${result.api}`, result);
    if (result.api == "get_chip_info") {
        ticks['refresh_chip_info'] = 0;
        server_info.chip = result.data;
        return;
    } else if (result.api == "get_config_wifi") {
        ticks['refresh_wifi_info'] = 0;
        config.value.wifi = toRef(result.data);
        return;
    } else if (result.api == "afe_get_config") {
        ticks['refresh_afe_config'] = 0;
        if (JSON.stringify(server_info.user_config) == JSON.stringify(server_info.set_config))
            server_info.set_config = toRef(JSON.parse(JSON.stringify(result.data)));
        server_info.user_config = toRef(result.data);
        return;
    } else if (result.api == "ota_get_config") {
        ticks['refresh_ota_config'] = 0;
        if (JSON.stringify(server_info.ota) == JSON.stringify(server_info.set_ota))
            server_info.set_ota = toRef(JSON.parse(JSON.stringify(result.data)));
        server_info.ota = toRef(result.data);
        return;
    } else if (result.api == "afe_set_chg") {
        ticks['afe_set_chg'] = 0;
        refresh_chip_info();
        return;
    } else if (result.api == "afe_set_dsg") {
        ticks['afe_set_dsg'] = 0;
        return;
    } else if (result.api == "afe_set_ae") {
        ticks['afe_set_ae'] = 0;
        return;
    } else if (result.api == "afe_clear_alert") {
        ticks['afe_clear_alert'] = 0;
        return;
    } else if (result.api == "afe_update_config") {
        ticks['afe_update_config'] = 0;
        if (typeof result.data === 'number') {
            if (result.data == 0) {
                ElMessage.success("配置已保存");
                refresh_afe_config();
            }
            else
                ElMessage.error("配置保存失败，错误码: " + result.data);
        } else if (typeof result.data === 'string') {
            if (result.data == 'No change')
                ElMessage.warning("配置未修改");
            else
                ElMessage.error("配置保存失败，错误码: " + result.data);
        }
        return;
    } else if (result.api == "ota_set_config") {
        ticks['ota_set_config'] = 0;
        ElMessage.success("OTA配置保存成功");
        refresh_ota_config();
        return;
    } else if (result.api == "ota_refresh_version") {
        ticks['refresh_ota_server_version'] = 0;
        refresh_ota_config();
        ElMessage.success("刷新成功");
        return;
    } else if (result.api == "ota_bin_from_server") {
        ticks['ota_update_app_from_server'] = 0;
        return;
    } else if (result.api == "ota_web_from_server") {
        ticks['ota_update_www_from_server'] = 0;
        return;
    } else if (result.api == "reboot") {
        ticks['reboot'] = 0;
        ElMessage.success("设备正在重启中......");
        return;
    } else if (result.api == "clear_event_log") {
        config.value.events = [];
        ticks['clear_event_log'] = 0;
        ElMessage.success("已清空所有事件");
        return;
    } else if (result.api == "wifi_connect") {
        return;
    } else if (result.api == "afe") {
        server_info.infos = result.data;
        config.value.info = server_info.infos
        return;
    } else if (result.api == "log") {
        if (result.data?.type == 0) {
            if (result.data?.attr == 0) {
                server_info.log_list.infos.sec.push(result.data.content);
                if (server_info.log_list.infos.sec.length > 300)/* 保留 5分钟 */
                    server_info.log_list.infos.sec.shift();
            }
            else if (result.data?.attr == 1) {
                server_info.log_list.infos.min.push(result.data.content);
                if (server_info.log_list.infos.min.length > 300)/* 保留 5小时 */
                    server_info.log_list.infos.min.shift();
                server_info.log_list.infos.day.push(result.data.content);/* 保留 2天 */
                if (server_info.log_list.infos.day.length > 2880)
                    server_info.log_list.infos.day.shift();
            }
            else if (result.data?.attr == 2) {
                server_info.log_list.infos.hour.push(result.data.content);
                if (server_info.log_list.infos.hour.length > 120)/* 保留 5天 */
                    server_info.log_list.infos.hour.shift();
            }
        } else if (result.data?.type == 1) {
            const events = server_info.log_list.events;
            events.push(result.data.content);
            if (events.length > 1440)
                events.shift();
        }
        return;
    }
    else if (result.api == "get_logs") {
        if (result.data?.events) {
            server_info.log_list.events = result.data.events;
            config.value.events = result.data.events;
        }
        if (result.data?.infos) {
            if (result.data.infos?.sec)
                server_info.log_list.infos.sec = result.data.infos.sec;
            if (result.data.infos?.min)
                server_info.log_list.infos.min = result.data.infos.min;
            if (result.data.infos?.hour)
                server_info.log_list.infos.hour = result.data.infos.hour;
            if (result.data.infos?.day)
                server_info.log_list.infos.day = result.data.infos.day;
            if (!config.value.log_mode)
                config.value.logs = server_info.log_list.infos.sec;
            else if (config.value.log_mode == 1)
                config.value.logs = server_info.log_list.infos.min;
            else if (config.value.log_mode == 2)
                config.value.logs = server_info.log_list.infos.hour;
            else if (config.value.log_mode == 3)
                config.value.logs = server_info.log_list.infos.day;
        }
        return;
    }
}

function api_req(api: string, data: any, name: string, timeoutString?: string, err_cb?: any, success_cb?: any) {
    let tick = Date.now();
    cb_list[name] = {};
    if (success_cb)
        cb_list[name].ok = success_cb;
    if (err_cb)
        cb_list[name].error = err_cb;
    if (name) {
        ticks[name] = tick;
        if (handles[name]) {
            clearTimeout(handles[name]);
        }
        handles[name] = setTimeout(() => {
            if (ticks[name]) {
                ElMessage.error(timeoutString);
                ticks[name] = 0; // 清除超时
                if (cb_list[name]?.error) {
                    cb_list[name].error();
                    delete cb_list[name].error; // 清除回调
                }
            }
        }, 3 * 1000); // 3秒后超时
    }
    Bus.emit("push.msg", {
        api,
        data: data || {}
    });
}

/* 获取设备物理地址 */
function refresh_chip_info() {
    api_req("get_chip_info", {}, 'refresh_chip_info', "获取设备物理信息超时");
}

function refresh_wifi_info() {
    api_req("get_config_wifi", {}, 'refresh_wifi_info', "获取设备WiFi信息超时");
}

function refresh_afe_config() {
    api_req("afe_get_config", {}, 'refresh_afe_config', "获取设备配置超时");
}

function refresh_ota_config() {
    api_req("ota_get_config", {}, 'refresh_ota_config', "获取OTA配置超时");
}

function refresh_logs() {
    axios.post("http://" + ws.host + "/get_logs").then((result) => {
        // console.log("get_logs", result);
        get_msg(result.data);
    }).catch((err) => {
        console.log("get_logs", err);
    })
}

function afe_clear_alert(enable: boolean) {
    api_req("afe_clear_alert", {}, 'afe_clear_alert', "清除设备警报状态超时");
}
function afe_set_chg(enable: boolean) {
    api_req("afe_set_chg", { enable }, 'afe_set_chg', "设置设备充电状态超时");
}

function afe_set_dsg(enable: boolean) {
    api_req("afe_set_dsg", { enable }, 'afe_set_dsg', "设置设备放电状态超时");
}
function afe_set_ae(enable: boolean) {
    api_req("afe_set_ae", { enable }, 'afe_set_ae', "设置设备主动均衡状态超时");
}
function afe_update_config(config: user_config) {
    api_req("afe_update_config", config, 'afe_update_config', "设置设备配置超时");
}
function ota_set_config() {
    let data = JSON.parse(JSON.stringify(server_info.set_ota));
    delete data.version;
    delete data.last;
    api_req("ota_set_config", data, 'ota_set_config', "设置OTA配置超时");
}
function refresh_ota_server_version() {
    api_req("ota_refresh_version", {}, 'refresh_ota_server_version', "更新 服务器 OTA 版本超时");
}
function ota_update_app_from_server() {
    api_req("ota_bin_from_server", {}, 'ota_update_app_from_server', "发送从服务器升级 APP 指令超时");
}
function ota_update_www_from_server() {
    api_req("ota_web_from_server", {}, 'ota_update_www_from_server', "发送从服务器升级 WEB 指令超时");
}


async function ota_http_req(url: string, data: Blob, offset?: number) {
    let header = {};
    let uploadData = data;
    if (offset && offset < data.size) {
        header['Content-Range'] = `bytes ${offset}-${data.size}/${data.size}`
        uploadData = data.slice(offset);
        console.log(data, uploadData)
    }
    const req_url = url
    let socket = await fetch(req_url, {
        method: "POST",
        // signal: controller.signal,
        // timeout: 5000, // 超时时间
        headers: header,
        body: uploadData
    })
    console.log(socket)
    // if (controller.signal.aborted) {
    //     return true;
    // }
    if (socket.status != 200) {
        console.log(socket)
        return "无法推送文件";
    }
    const reader = socket.body.getReader(); // 获取reader
    console.log(reader.read)
    while (true) {
        // 取值, value 是后端返回流信息, done 表示后端结束流的输出
        const { value, done } = await reader.read();
        // console.log(value, value.length)
        // if (controller.signal.aborted)
        //     break
        // if (!socket.ok) break;
        if (done) break;
        if (value.length > 10) {
            let value_str = new TextDecoder('utf-8').decode(value)
            console.log(value, value.size, value_str)
            // return "无法推送文件, 接收中断 " + value_str;
        }
        // device.progress = parseInt(value_str);
        // if (isNaN(device.progress)) {
        //     if (value.length == 1)
        //         device.progress = value[0];
        //     else
        //         return otaTaskFailed(device, "无法推送文件", value_str)
        // }
        // console.log(typeof device.progress, device.progress, value_str);
        let progress = value[value.length - 1];
        // device.tick = Date.now(); // 更新时间
        if (progress == 100) {
            console.log(`OTA success`)
        }
        console.log(progress, value);
    }
}

function ota_update_app_from_file(file_data: Blob, url?: string) {
    ota_http_req(url ? url : "http://" + ws.host + "/upgrade/stream/app", file_data);
    // ota_http_req(url ? url : "/upgrade/stream/app", file_data);

    // axios.post(url ? url : "/upgrade/stream/app", f).then((result) => {
    //     console.log("ota_update_app_from_file", result);
    // }).catch((err) => {
    //     console.log("ota_update_app_from_file", err);
    // })
}
function ota_update_www_from_file(file_data: Blob, url?: string) {
    ota_http_req(url ? url : "http://" + ws.host + "/upgrade/stream/www", file_data);
    // ota_http_req(url ? url : "/upgrade/stream/www", file_data);
    // axios.post(url ? url : "/upgrade/stream/www", f).then((result) => {
    //     console.log("ota_update_www_from_file", result);
    // }).catch((err) => {
    //     console.log("ota_update_www_from_file", err);
    // })
}

function ota_app_rollback(url?: string) {
    fetch(url ? url : "http://" + ws.host + "/upgrade/ctrl/app",
        {
            method: "POST",
            body: JSON.stringify({ back: true })
        }
    ).then((result) => {
        ElMessage.success("回滚成功");
        ElMessage.success("设备正在重启");
        console.log("回滚成功", result.text());
    }).catch((err) => {
        ElMessage.error("回滚失败: " + JSON.stringify(err));
        console.log("回滚失败", err);
    })
}
// 定义一个reboot函数，用于设置设备重启状态
function reboot() {
    // 调用api_req函数，传入参数"reboot"，空对象，"reboot"，"设置设备重启状态回复超时"
    api_req("reboot", {}, 'reboot', "设置设备重启状态回复超时");
}
function clear_event() {
    api_req("clear_event_log", {}, 'clear_event_log', "清空已记录的所有事件");
}

Bus.on("update:msg", get_msg);
config.value["server"] = server_info; // 设备信息

export default {
    refresh_chip_info,
    refresh_wifi_info,
    refresh_afe_config,
    refresh_ota_config,
    refresh_logs,
    afe_clear_alert,
    afe_set_chg,
    afe_set_dsg,
    afe_set_ae,
    afe_update_config,
    ota_set_config,
    refresh_ota_server_version,
    ota_update_app_from_server,
    ota_update_www_from_server,
    ota_update_app_from_file,
    ota_update_www_from_file,
    ota_app_rollback,
    reboot,
    clear_event,
    ticks,
};
